package chen.videoedit;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * 视频截取
 */
public class InterceptionActivity extends BasisActivity {
    private EditText start_et;
    private EditText end_et;
    private View bt;
    private MediaExtractor extractor;
    private String path;
    private int videoTrack;//视轨
    private MediaFormat VideomediaFormat;//视频格式


    private int audioTrack;//音轨
    private MediaFormat AudiomediaFormat;//音频格式
    private String path_save;
    private MediaMuxer mediaMuxer;
    private ByteBuffer inputBuffer;
    private long start_tag;
    private long end_tag;


    @Override
    public int setlayoutResID() {
        return R.layout.activity_interception;
    }

    @Override
    public void initialView(Bundle arg0) {
        start_et = (EditText) findViewById(R.id.interception_start);
        end_et = (EditText) findViewById(R.id.interception_end);
        findViewById(R.id.interception_bt).setOnClickListener(this);

    }

    @Override
    public void setActivity() {
        path = Environment.getExternalStorageDirectory() + "/test.MP4";//目标视频路径
        path_save = Environment.getExternalStorageDirectory() + "/截取test.mp4";//截取视频路径
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.interception_bt:
                String s = start_et.getText().toString();
                String e = end_et.getText().toString();
                if (TextUtils.isEmpty(s) || TextUtils.isEmpty(e)) {

                    Toast("填写错误");
                    return;
                }
                start_tag = Long.parseLong(s);
                end_tag = Long.parseLong(e);

                MyThread thread = new MyThread();
                thread.start();
                break;

        }

    }


    class MyThread extends Thread {
        @Override
        public void run() {
            interception(start_tag, end_tag);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast("截取完成");
                }
            });
        }
    }


    /**
     * 截取单位秒
     */
    private void interception(Long start, Long end) {

        start = start * 1000 * 1000;//转毫秒
        end = end * 1000 * 1000;//转毫秒

        extractor = new MediaExtractor();//初始化分离器
        try {
            extractor.setDataSource(path);
        } catch (IOException e) {
            Log.e("error", "MediaExtractor初始化失败" + e.toString());
        }
        int count = extractor.getTrackCount();
        //获取每个轨道的信息
        for (int i = 0; i < count; i++) {
            MediaFormat mediaFormat;
            if (extractor != null) {
                mediaFormat = extractor.getTrackFormat(i);
                String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith("video/")) {
                    videoTrack = i;
                    VideomediaFormat = mediaFormat;
                }
                if (mime.startsWith("audio/")) {
                    audioTrack = i;
                    AudiomediaFormat = mediaFormat;
                    Log.e("lll", AudiomediaFormat.toString());
                }
            }
        }
        //判断截取时间是否合法
        if (start < end) {
            long duration = VideomediaFormat.getLong(MediaFormat.KEY_DURATION);//视频时长
            if (end > duration) {
                return;
            }
        } else {
            return;
        }


        try {
            mediaMuxer = new MediaMuxer(path_save, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);//初始化封装器
        } catch (IOException e) {
            Log.e("error", "MediaMuxer初始化失败" + e.toString());
        }
        int videoTrackIndex = mediaMuxer.addTrack(VideomediaFormat);//为封装器 添加视轨
        int audioTrackIndex = mediaMuxer.addTrack(AudiomediaFormat);//为封装器 添加音轨
        mediaMuxer.start();
        //分配缓冲
        inputBuffer = ByteBuffer.allocate(VideomediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE));
        interceptionVideo(start, end, videoTrackIndex);
        interceptionAudio(start, end, audioTrackIndex);
    }


    /**
     * 截取视频
     */
    private void interceptionVideo(Long start, Long end, int videoTrackIndex) {

        extractor.selectTrack(videoTrack);//选择视频部分
        MediaCodec.BufferInfo videoInfo = new MediaCodec.BufferInfo();//数据描述
        long videoSampleTime = 0;//获取源视频相邻帧之间的时间间隔
        {
            extractor.readSampleData(inputBuffer, 0);
            if (extractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC)
                extractor.advance();
            extractor.readSampleData(inputBuffer, 0);
            long firstVideoPTS = extractor.getSampleTime();
            extractor.advance();
            extractor.readSampleData(inputBuffer, 0);
            long SecondVideoPTS = extractor.getSampleTime();
            videoSampleTime = Math.abs(SecondVideoPTS - firstVideoPTS);//每一帧停留的时间  帧率 1秒处于每一帧停留的时间
        }

        //选择起点
        extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
        while (true) {
            int sampleSize = extractor.readSampleData(inputBuffer, 0);
            if (sampleSize < 0) {
                extractor.unselectTrack(videoTrack);    //这里一定要释放选择的轨道，不然另一个轨道就无法选中了
                break;
            }
            long presentationTimeUs = extractor.getSampleTime(); //获取当前时间戳
            int sampleFlag = extractor.getSampleFlags();//获取帧类型，只能识别是否为I帧

            if (presentationTimeUs > end) {  //剪辑时间到了就跳出
                extractor.unselectTrack(videoTrack);
                break;
            }
            extractor.advance();
            videoInfo.offset = 0;
            videoInfo.size = sampleSize;
            videoInfo.flags = sampleFlag;
            mediaMuxer.writeSampleData(videoTrackIndex, inputBuffer, videoInfo);
            videoInfo.presentationTimeUs += videoSampleTime;//presentationTimeUs;
        }


    }


    /**
     * 截取音频
     */
    private void interceptionAudio(Long start, Long end, int audioTrackIndex) {
        extractor.selectTrack(audioTrack);//音频部分
        MediaCodec.BufferInfo audioInfo = new MediaCodec.BufferInfo();
        audioInfo.presentationTimeUs = 0;

        long audioSampleTime = 0;//获取音频帧时长
        {
            extractor.readSampleData(inputBuffer, 0);
            //skip first sample
            if (extractor.getSampleTime() == 0)
                extractor.advance();
            extractor.readSampleData(inputBuffer, 0);
            long firstAudioPTS = extractor.getSampleTime();
            extractor.advance();
            extractor.readSampleData(inputBuffer, 0);
            long SecondAudioPTS = extractor.getSampleTime();
            audioSampleTime = Math.abs(SecondAudioPTS - firstAudioPTS);
        }


        extractor.seekTo(start, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
        while (true) {
            int sampleSize = extractor.readSampleData(inputBuffer, 0);
            if (sampleSize < 0) {
                extractor.unselectTrack(audioTrack);
                break;
            }
            long presentationTimeUs = extractor.getSampleTime();
            if (presentationTimeUs > end) {
                extractor.unselectTrack(audioTrack);
                break;
            }
            extractor.advance();
            audioInfo.offset = 0;
            audioInfo.size = sampleSize;
            mediaMuxer.writeSampleData(audioTrackIndex, inputBuffer, audioInfo);
            audioInfo.presentationTimeUs += audioSampleTime;//presentationTimeUs;
        }
//全部写完后释放
        mediaMuxer.stop();
        mediaMuxer.release();
        extractor.release();
        extractor = null;
    }


}
